﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Xml;
using System.Collections.Generic;
using WeChat.Common;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json.Linq;
using WeChat.Common2;
using Models;
using BLL;
using System.Threading;

namespace WeChat.JsSDK.lib
{

    /*======================微信支付===================*/
    public class WxPayApi
    {


        //统一下单接口,传递参数组成xml字符串
        public static string unifiedorder(string Userid, int money, string attachs, string order_No,string address, string type)
        {
            ApplicationLog.Write("attachs:" + attachs);
            XmlDocument xml = new XmlDocument();
            XmlElement first = xml.CreateElement("xml");
            xml.AppendChild(first);
            XmlElement appid = xml.CreateElement("appid");      //公众账号ID
            appid.InnerText = GetSdkParams.getAppId();
            first.AppendChild(appid);
            XmlElement attach = xml.CreateElement("attach");     //附加数据，在查询API和支付通知中原样返回，该字段主要用于商户携带订单的自定义数据
            attach.InnerText = attachs;

            first.AppendChild(attach);
            XmlElement body = xml.CreateElement("body");             //商品或支付单简要描述
            if (attachs == "addmoney")
            {
                body.InnerText = Config.body;
            }
            else {
                body.InnerText = "订餐消费";
            }
                 
           
            first.AppendChild(body);
            XmlElement mch_id = xml.CreateElement("mch_id");       //微信支付分配的商户号
            mch_id.InnerText = Config.getMerchantNum();//ConfigurationSettings.AppSettings["merchantNum"].ToString();
            first.AppendChild(mch_id);
            XmlElement nonce_str = xml.CreateElement("nonce_str");   //随机字符串，长度不超过32位
            nonce_str.InnerText = GetSdkParams.getNonceStr(32);
            first.AppendChild(nonce_str);
            XmlElement notify_url = xml.CreateElement("notify_url");   //接收微信支付异步通知回调地址
            notify_url.AppendChild(xml.CreateCDataSection(Config.ReUrl));
            first.AppendChild(notify_url);
            if (type == "JSAPI")
            {
                XmlElement openid = xml.CreateElement("openid");    //用户标识，trade_type=JSAPI时，此参数必传
                openid.AppendChild(xml.CreateCDataSection(Userid));
                first.AppendChild(openid);
            }
            else if (type == "NATIVE")
            {
                XmlElement product_id = xml.CreateElement("product_id");    //二维码商品ID，用户自定义。trade_type=NATIVE时，此参数必传
                product_id.AppendChild(xml.CreateCDataSection(Config.product_id));
                first.AppendChild(product_id);
            }
            XmlElement out_trade_no = xml.CreateElement("out_trade_no");   //商户订单号(自定义)，当前时间戳加上6位随机数组成
            out_trade_no.InnerText = order_No;

            //XmlElement address1 = xml.CreateElement("address");   //商户订单号(自定义)，当前时间戳加上6位随机数组成
            //address1.InnerText = address;

            first.AppendChild(out_trade_no);
            XmlElement total_fee = xml.CreateElement("total_fee");       //订单总金额，单位为分
            total_fee.InnerText = money.ToString();
            first.AppendChild(total_fee);
            XmlElement spbill_create_ip = xml.CreateElement("spbill_create_ip");   //APP和网页支付提交用户端ip
           
            spbill_create_ip.AppendChild(xml.CreateCDataSection(Config.ip));
            first.AppendChild(spbill_create_ip);
            XmlElement trade_type = xml.CreateElement("trade_type");   //交易类型，取值如下：JSAPI 网页支付，NATIVE 扫码支付，APP 移动应用支付
            trade_type.InnerText = type;
            first.AppendChild(trade_type);  
            XmlElement sign = xml.CreateElement("sign");   //签名         
            sign.InnerText = toSign(exChangeXml(first));
            first.AppendChild(sign);
            string b = xml.InnerXml;
            ApplicationLog.Write("统一下单xml:" + b);
            return b;
        }


        //调用统一下单的参数发送post请求获得返回结果
        public static string getUnifiedOrder(string userid, int money, string attach, string order_No, string address,string type)
        {
            string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            string xml = unifiedorder(userid, money, attach, order_No, address,type);
            var start = DateTime.Now;
            string response = HttpService.Post(xml, url, false, 6);
            var end = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);
            ApplicationLog.Write("支付类型：" + type);
            ApplicationLog.Write("发送统一下单xml数据post请求返回结果：" + response);
            ApplicationLog.Write("调用统一下单的参数发送post请求获得返回结果所用时间：" + timeCost + "毫秒");
            return response;
        }


        //要的执行方法
        public static object loker = new object();
        //对统一下单返回结果解析，判断下单成功后，支付方式为JSAPI支付则返回prepay_id，扫码支付则返回code_url
        public static string getJsApi(string userid, int money, string attach, string order_No,string address, string type)
       // public static string getJsApi(string userid, int money, string attach, string order_No, string type)
        {
                     string responce = getUnifiedOrder(userid, money, attach, order_No,address, type);
            string prepay_id = "", code_url = "";
            XmlDocument xml = new XmlDocument();
            xml.LoadXml(responce);
          
            XmlNode xn = xml.SelectSingleNode("xml");
            string return_code = xn.SelectSingleNode("return_code").InnerText;
   
            if (return_code.Equals("SUCCESS"))
            {
                string result_code = xn.SelectSingleNode("result_code").InnerText;
                if (result_code.Equals("SUCCESS"))
                {
                    prepay_id = xn.SelectSingleNode("prepay_id").InnerText; //JSAPI下单成功，得到prepay_id
                    if (type == "NATIVE")
                    {
                        code_url = xn.SelectSingleNode("code_url").InnerText; //扫码下单成功，得到code_url
                        ApplicationLog.Write("扫码统一下单返回code_url:" + code_url);   
                        return code_url;
                    }
                    ApplicationLog.Write("下单成功");


                    Thread thread = new Thread(() =>
                    {
                        Thread.Sleep(300);
                        lock (loker)
                        {
                            MenuReservationBLL mb = new MenuReservationBLL();
                            //解析购物车当前点菜品列表
                            var Listdetails = mb.MeuListOrder(order_No);
                            foreach (DataRow item in Listdetails.Rows)
                            {
                                var orderNum = Convert.ToInt32(item["orderNum"]);
                                var MenuId = item["MenuId"].ToString();
                                var OnSaleIdm = item["OnSaleId"].ToString();
                                var canteen = item["canteen"].ToString();
                                int Menu = mb.updateMenulist(orderNum, MenuId, OnSaleIdm, canteen);

                                ApplicationLog.Write("微信付款成功后份数扣除：份数：" + orderNum + ",菜品ID：" + MenuId + ",修改状态：" + Menu);

                            }
                        }
                    });

                    thread.Start();
                    thread.Join();

                }
                else
                {    
                    ApplicationLog.Write("下单失败，err_code：" + xn.SelectSingleNode("err_code").InnerText);
                }
            }
            else
            {
                ApplicationLog.Write("签名失败");
            }


            return prepay_id;



        }


        //JSAPI支付，返回JsAPI支付json参数
        /***********注：timestamp参数必须为string类型，否则ios系统会无法识别导致支付失败***********/
        public static string getPayJson(string userid, string money,string attach,string orderid,string address)
        //public static string getPayJson(string userid, string money, string attach, string orderid)
        {


            ApplicationLog.Write("attach"+ attach);
            string order_No = "";
            if (attach == "addmoney")
            {
                order_No = GetSdkParams.getTimestamp().ToString() + GetSdkParams.getNonceStr(6);
            }
            else {
                order_No = orderid;
            }

            string prepay_id = getJsApi(userid, Int32.Parse(money), attach, order_No, address,"JSAPI");
            //string prepay_id = getJsApi(userid, Int32.Parse(money), attach, order_No, "JSAPI");
            if (prepay_id != "")
            {
                //项目地址
                string srcUrl = ConfigurationManager.AppSettings["srcUrl"];
                JObject jo = new JObject();
                //存入字典格式,排序生成签名
                SortedDictionary<string, object> sd = new SortedDictionary<string, object>();
                jo.Add("appId", GetSdkParams.getAppId());
                sd.Add("appId", GetSdkParams.getAppId());
                string timeStamp = GetSdkParams.getTimestamp();
                jo.Add("timeStamp", timeStamp);
                sd.Add("timeStamp", timeStamp);
                string nonceStr = GetSdkParams.getNonceStr(32);
                jo.Add("nonceStr", nonceStr);
                sd.Add("nonceStr", nonceStr);
                jo.Add("package", "prepay_id=" + prepay_id);
                sd.Add("package", "prepay_id=" + prepay_id);
                jo.Add("signType", "MD5");
                sd.Add("signType", "MD5");



                jo.Add("paySign", toSign(sd));
                ApplicationLog.Write("JsApiPay参数：" + jo.ToString());
                return jo.ToString();
            }
            else
            {
                return "";
            }
        }

        /*======================刷卡支付===================*/
        /// <summary>
        /// 刷卡支付下单
        /// </summary>
        /// <param name="cardID"></param>
        /// <param name="money"></param>
        /// <param name="attachs"></param>
        /// <param name="order_No"></param>
        /// <param name="auth_codes"></param>
        /// <returns></returns>
        public static string micropay(string cardID, int money, string attachs, string order_No, string auth_codes)
        {
            XmlDocument xml = new XmlDocument();
            XmlElement first = xml.CreateElement("xml");
            xml.AppendChild(first);
            XmlElement appid = xml.CreateElement("appid");      //公众账号ID
            appid.InnerText = GetSdkParams.getAppId();
            first.AppendChild(appid);
            XmlElement mch_id = xml.CreateElement("mch_id");       //微信支付分配的商户号
            mch_id.InnerText = Config.getMerchantNum();
            first.AppendChild(mch_id);
            XmlElement nonce_str = xml.CreateElement("nonce_str");   //随机字符串，长度不超过32位
            nonce_str.InnerText = GetSdkParams.getNonceStr(32);
            first.AppendChild(nonce_str);
            XmlElement body = xml.CreateElement("body");
            body.InnerText = attachs;                                //商品或支付单简要描述
            first.AppendChild(body);
            XmlElement out_trade_no = xml.CreateElement("out_trade_no");   //商户订单号(自定义)，当前时间戳加上6位随机数组成
            out_trade_no.InnerText = order_No;
            first.AppendChild(out_trade_no);
            XmlElement total_fee = xml.CreateElement("total_fee");       //订单总金额，单位为分
            total_fee.InnerText = money.ToString();
            first.AppendChild(total_fee);
            XmlElement spbill_create_ip = xml.CreateElement("spbill_create_ip");   //调用微信支付API的机器IP
            spbill_create_ip.AppendChild(xml.CreateCDataSection(Config.ip));
            first.AppendChild(spbill_create_ip);
            XmlElement auth_code = xml.CreateElement("auth_code");   //	扫码支付授权码，设备读取用户微信中的条码或者二维码信息
            auth_code.AppendChild(xml.CreateCDataSection(auth_codes));
            first.AppendChild(auth_code);
          
       
           
            XmlElement sign = xml.CreateElement("sign");   //签名         
            sign.InnerText = toSign(exChangeXml(first));
            first.AppendChild(sign);
            string b = xml.InnerXml;
            ApplicationLog.Write("统一下单xml:" + b);
            return b;
        }
        //调用下单的参数发送post请求获得返回结果
        public static string getMicropay(string cardID, int money, string attach, string order_No, string auth_code)
        {
            string url = "https://api.mch.weixin.qq.com/pay/micropay";
            string xml = micropay(cardID, money, attach, order_No, auth_code);
            var start = DateTime.Now;
            string response = HttpService.Post(xml, url, false, 6);
            var end = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);
            ApplicationLog.Write("发送统一下单xml数据post请求返回结果：" + response);
            ApplicationLog.Write("调用统一下单的参数发送post请求获得返回结果所用时间：" + timeCost + "毫秒");
            return response;
        }
        //对下单返回结果解析
        public static void SlotCardApi(object o)
        {
            var obj = o as Sparameter;
            string responce = getMicropay(obj.cardID, Int32.Parse(obj.money), obj.attach, obj.order_No, obj.auth_code);
        
            XmlDocument xml = new XmlDocument();
            xml.LoadXml(responce);

            XmlNode xn = xml.SelectSingleNode("xml");
            string return_code = xn.SelectSingleNode("return_code").InnerText;
            ApplicationLog.Write("return_code : " + return_code);
            if (return_code.Equals("SUCCESS"))
            {
                SlotCardPay sc = new SlotCardPay();
                string result_code = xn.SelectSingleNode("result_code").InnerText;
                ApplicationLog.Write("result_code : " + result_code);
               // string  err_code = xn.SelectSingleNode("err_code").InnerText;
                //ApplicationLog.Write("err_code : " + err_code);
                if (result_code.Equals("SUCCESS"))
                {
                    ApplicationLog.Write("MicroPay", "Mircopay success, return order query result : " + responce);
                    sc.openid = xn.SelectSingleNode("openid").InnerText;
                    ApplicationLog.Write("openid:"+sc.openid);
                    sc.is_subscribe = xn.SelectSingleNode("is_subscribe").InnerText;
                    sc.trade_type = xn.SelectSingleNode("trade_type").InnerText;
                    sc.bank_type = xn.SelectSingleNode("bank_type").InnerText;
                    sc.fee_type = xn.SelectSingleNode("fee_type").InnerText;
                    sc.total_fee = xn.SelectSingleNode("total_fee").InnerText;
                    sc.settlement_total_fee = "";
                    sc.coupon_fee = "";
                    sc.cash_fee_type = "";
                    sc.cash_fee = xn.SelectSingleNode("cash_fee").InnerText;
                    sc.transaction_id = xn.SelectSingleNode("transaction_id").InnerText;
                    sc.out_trade_no = xn.SelectSingleNode("out_trade_no").InnerText;
                    sc.attachs = xn.SelectSingleNode("attach").InnerText;
                    sc.time_end = xn.SelectSingleNode("time_end").InnerText;
                    sc.promotion_detail = "";
                    int i = WxPayAddBLL.SlotCardPayRecord(sc);
                    ApplicationLog.Write("i:" +i);
                  
                }
                //  else if(err_code.Equals("USERPAYING")|| err_code.Equals("SYSTEMERROR"))
                else if (xn.SelectSingleNode("err_code").InnerText=="USERPAYING" || xn.SelectSingleNode("err_code").InnerText =="SYSTEMERROR")
                {
                    int queryTimes = 10;//查询次数计数器
                    while (queryTimes-- > 0)
                    {
                        int succResult = 0;//查询结果
                        string  queryResult = Query(obj.order_No, out succResult);
                        XmlDocument xmls = new XmlDocument();
                        xmls.LoadXml(queryResult);

                        XmlNode xns = xmls.SelectSingleNode("xml");
                      
                        //如果需要继续查询，则等待6s后继续
                        if (succResult == 2)
                        {
                            Thread.Sleep(6000);
                            continue;
                        }
                        //查询成功,返回订单查询接口返回的数据
                        else if (succResult == 1)
                        {
                            ApplicationLog.Write("MicroPay", "Mircopay success, return order query result : " + queryResult);
                            sc.openid = xns.SelectSingleNode("openid").InnerText;
                            sc.is_subscribe = xns.SelectSingleNode("is_subscribe").InnerText;
                            sc.trade_type = xns.SelectSingleNode("trade_type").InnerText;
                            sc.bank_type = xns.SelectSingleNode("bank_type").InnerText;
                            sc.fee_type = xns.SelectSingleNode("fee_type").InnerText;
                            sc.total_fee = xns.SelectSingleNode("total_fee").InnerText;
                            sc.settlement_total_fee ="";
                            sc.coupon_fee ="";
                            sc.cash_fee_type ="";
                            sc.cash_fee = xns.SelectSingleNode("cash_fee").InnerText;
                            sc.transaction_id = xns.SelectSingleNode("transaction_id").InnerText;
                            sc.out_trade_no = xns.SelectSingleNode("out_trade_no").InnerText;
                            sc.attachs = xns.SelectSingleNode("attach").InnerText;
                            sc.time_end = xns.SelectSingleNode("time_end").InnerText;
                            sc.promotion_detail = "";
                            int i = WxPayAddBLL.SlotCardPayRecord(sc);
                            if (i > 0)
                            {
                                return;
                            }
                          
                        }
                        //订单交易失败，直接返回刷卡支付接口返回的结果，失败原因会在err_code中描述
                        else
                        {
                            ApplicationLog.Write("订单交易失败，err_code：" + xns.SelectSingleNode("err_code").InnerText);
                           // return "FAIL";
                        }
                    }
                    //if (!Cancel(obj.order_No))
                    //{
                    //    ApplicationLog.Write("MicroPay", "Reverse order failure");
                      
                    //}

                  //  return "撤销订单";
                    // return "0";
                }
                else
                {
                    ApplicationLog.Write("下单失败，err_code：" + xn.SelectSingleNode("err_code").InnerText);
                  //  return "FAIL";
                }
            }
            else
            {
              //  return "FAIL";
            }
           
        }
        //撤销订单
        public static bool Cancel(string transaction_id, int depth = 0)
        {
            if (depth > 10)
            {
                return false;
            }
            string responce = Reverse(transaction_id);

            XmlDocument xml = new XmlDocument();
            xml.LoadXml(responce);

            XmlNode xn = xml.SelectSingleNode("xml");
            string return_code = xn.SelectSingleNode("return_code").InnerText;
           string  recall = xn.SelectSingleNode("recall").InnerText;
            //接口调用失败
           
            if (!return_code.Equals("SUCCESS"))
            {
                return false;
            }

            //如果结果为success且不需要重新调用撤销，则表示撤销成功
            if (!return_code.Equals("SUCCESS") && !recall.Equals("N"))
            {
                return true;
            }
            else if (recall.Equals("N"))
            {
                return Cancel(transaction_id, ++depth);
            }
            return false;
        }
        public static string Reverse(string  transaction_ids, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
            //检测必填参数
            XmlDocument xml = new XmlDocument();
            XmlElement first = xml.CreateElement("xml");
            xml.AppendChild(first);
            XmlElement appid = xml.CreateElement("appid");      //公众账号ID
            appid.InnerText = GetSdkParams.getAppId();
            first.AppendChild(appid);
            XmlElement mch_id = xml.CreateElement("mch_id");       //微信支付分配的商户号
            mch_id.InnerText = Config.getMerchantNum();//ConfigurationSettings.AppSettings["merchantNum"].ToString();
            first.AppendChild(mch_id);
            XmlElement nonce_str = xml.CreateElement("nonce_str");   //随机字符串，长度不超过32位
            nonce_str.InnerText = GetSdkParams.getNonceStr(32);
            first.AppendChild(nonce_str);
            XmlElement transaction_id = xml.CreateElement("transaction_id");   //随机字符串，长度不超过32位
            nonce_str.InnerText = transaction_ids;
            first.AppendChild(transaction_id);
            XmlElement sign = xml.CreateElement("sign");   //签名         
            sign.InnerText = toSign(exChangeXml(first));
            first.AppendChild(sign);
            string b = xml.InnerXml;
            ApplicationLog.Write("撤销订单xml:" + b);
            ApplicationLog.Write("WxPayApi", "Reverse request : " + b);
            var start = DateTime.Now;//请求开始时间
            string response = HttpService.Post(b, url, true, timeOut);

            ApplicationLog.Write("WxPayApi", "Reverse response : " + response);

            var end = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);
            return response;
        }
        //查询订单
        public static string getSelect(string order_No)
        {
            int queryTimes = 10;//查询次数计数器
            while (queryTimes-- > 0)
            {
                int succResult = 0;//查询结果
                string queryResult = Query(order_No, out succResult);
                XmlDocument xmls = new XmlDocument();
                xmls.LoadXml(queryResult);

                XmlNode xns = xmls.SelectSingleNode("xml");

                //如果需要继续查询，则等待6s后继续
                if (succResult == 2)
                {
                    Thread.Sleep(6000);
                    continue;
                }
                //查询成功,返回订单查询接口返回的数据
                else if (succResult == 1)
                {
                    ApplicationLog.Write("MicroPay", "Mircopay success, return order query result : " + queryResult);
                    return "SUCCESS";
                  
                }
                //订单交易失败，直接返回刷卡支付接口返回的结果，失败原因会在err_code中描述
                else
                {
                    ApplicationLog.Write("订单交易失败，err_code：" + xns.SelectSingleNode("err_code").InnerText);
                    return "FAIL";
                }
            }
            if (!Cancel(order_No))
            {
                ApplicationLog.Write("MicroPay", "Reverse order failure");

            }

            return "撤销订单";
            // return "0";
        }

        public static string  Query(string order_No, out int succCode)
        {
            string result = OrderQuery(order_No);
            XmlDocument xml = new XmlDocument();
            xml.LoadXml(result);
            XmlNode xn = xml.SelectSingleNode("xml");
            string return_code = xn.SelectSingleNode("return_code").InnerText;

            if (return_code.Equals("SUCCESS")&& return_code.Equals("SUCCESS"))
            {
               string trade_state= xn.SelectSingleNode("trade_state").InnerText;
                //支付成功
                if (trade_state.Equals("SUCCESS"))
                {
                    succCode = 1;
                    return result;
                }
                //用户支付中，需要继续查询
                else if (trade_state.Equals("USERPAYING"))
                {
                    succCode = 2;
                    return result;
                }
            }
             string err_code = xn.SelectSingleNode("err_code").InnerText;
            //如果返回错误码为“此交易订单号不存在”则直接认定失败
            if (err_code.Equals("ORDERNOTEXIST"))
            {
                succCode = 0;
            }
            else
            {
                //如果是系统错误，则后续继续
                succCode = 2;
            }
            return result;
        }

        public static string OrderQuery(string order_No, int timeOut = 6)
        {
            string url = "https://api.mch.weixin.qq.com/pay/orderquery";
            XmlDocument xml = new XmlDocument();
            XmlElement first = xml.CreateElement("xml");
            xml.AppendChild(first);
            XmlElement appid = xml.CreateElement("appid");      //公众账号ID
            appid.InnerText = GetSdkParams.getAppId();
            first.AppendChild(appid);
            XmlElement mch_id = xml.CreateElement("mch_id");       //微信支付分配的商户号
            mch_id.InnerText = Config.getMerchantNum();//ConfigurationSettings.AppSettings["merchantNum"].ToString();
            first.AppendChild(mch_id);
            XmlElement nonce_str = xml.CreateElement("nonce_str");   //随机字符串，长度不超过32位
            nonce_str.InnerText = GetSdkParams.getNonceStr(32);
            first.AppendChild(nonce_str);
            XmlElement out_trade_no = xml.CreateElement("out_trade_no");   //随机字符串，长度不超过32位
            out_trade_no.InnerText = order_No;
            first.AppendChild(out_trade_no);
            XmlElement sign = xml.CreateElement("sign");   //签名         
            sign.InnerText = toSign(exChangeXml(first));
            first.AppendChild(sign);
            string b = xml.InnerXml;
            ApplicationLog.Write("查询订单xml:" + b);
            var start = DateTime.Now;

            ApplicationLog.Write("WxPayApi", "OrderQuery request : " + b);
            string response = HttpService.Post(b, url, false, timeOut);//调用HTTP通信接口提交数据
            ApplicationLog.Write("WxPayApi", "OrderQuery response : " + response);

            var end = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);//获得接口耗时
            return response;
                                                                 


        }

        /// <summary>
        /// 退款
        /// </summary>
        /// <param name="transaction_id"></param>
        /// <param name="out_trade_no"></param>
        /// <param name="total_fee"></param>
        /// <param name="refund_fee"></param>
        /// <returns></returns>
        public static string refund( string orderid, string totalmoney, string refundmoney)
        {
            XmlDocument xml = new XmlDocument();
            XmlElement first = xml.CreateElement("xml");
            xml.AppendChild(first);
            XmlElement appid = xml.CreateElement("appid");      //公众账号ID
            appid.InnerText = GetSdkParams.getAppId();
            first.AppendChild(appid);
            XmlElement mch_id = xml.CreateElement("mch_id");       //微信支付分配的商户号
            mch_id.InnerText = Config.getMerchantNum();
            first.AppendChild(mch_id);
            XmlElement nonce_str = xml.CreateElement("nonce_str");   //随机字符串，长度不超过32位
            nonce_str.InnerText = GetSdkParams.getNonceStr(32);
            first.AppendChild(nonce_str);
            XmlElement out_trade_no = xml.CreateElement("out_trade_no");      //商户订单号
            out_trade_no.InnerText = orderid;           
            first.AppendChild(out_trade_no);
            XmlElement total_fee = xml.CreateElement("total_fee");      //订单总金额
            total_fee.InnerText = totalmoney.ToString();
            first.AppendChild(total_fee); 
            XmlElement refund_fee = xml.CreateElement("refund_fee");   //退款金额
            refund_fee.InnerText = refundmoney.ToString();
            first.AppendChild(refund_fee);  
            XmlElement out_refund_no = xml.CreateElement("out_refund_no");
            out_refund_no.InnerText = GenerateOutTradeNo();
            first.AppendChild(out_refund_no);     //随机生成商户退款单号


            XmlElement sign = xml.CreateElement("sign");   //签名         
            sign.InnerText = toSign(exChangeXml(first));
            first.AppendChild(sign);

            string b = xml.InnerXml;
            //WxPayData result = WxPayApi.Refund(data);//提交退款申请给API，接收返回数据
            ApplicationLog.Write("申请退款xml:" + b);
            return b;
        }
        public static string getrefund(string orderid, string  totalmoney, string refundmoney)
        {
            string url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
            string xml = refund(orderid, totalmoney, refundmoney);
            var start = DateTime.Now; 
            string response = HttpService.Post(xml, url, true, 6);
            var end = DateTime.Now;
            int timeCost = (int)((end - start).TotalMilliseconds);
           
            ApplicationLog.Write("发送退款xml数据post请求返回结果：" + response);
            ApplicationLog.Write("调用退款 的参数发送post请求获得返回结果所用时间：" + timeCost + "毫秒");
            return response;
        }
        public static string getrefundresult(string orderid, string totalmoney, string refundmoney)
        {
            string responce = getrefund(orderid, totalmoney, refundmoney);
            XmlDocument xml = new XmlDocument();
            xml.LoadXml(responce);
            //XmlNodeList xnl = xml.DocumentElement.ChildNodes;
            XmlNode xn = xml.SelectSingleNode("xml");
            string return_code = xn.SelectSingleNode("return_code").InnerText;
            if (return_code.Equals("SUCCESS"))
            {
                //out_trade_no 
              string  out_trade_no = xn.SelectSingleNode("out_trade_no").InnerText;
                ApplicationLog.Write("调用退款接口，返回订单号：" + out_trade_no);
            }
            else
            {
                ApplicationLog.Write("签名失败");
            }
            return "";
        }
        /**
       * 根据当前系统时间加随机序列来生成订单号
        * @return 订单号
       */
        public static string GenerateOutTradeNo()
        {
            var ran = new Random();
            return string.Format("{0}{1}{2}", WxPayConfig.mchID, DateTime.Now.ToString("yyyyMMddHHmmss"), ran.Next(999));
        }


        //将xml类型转换成字典类型
        public static SortedDictionary<string, object> exChangeXml(XmlElement xml)
        {
            //将统一下单xml存入字典格式
            SortedDictionary<string, object> sd = new SortedDictionary<string, object>();
            foreach (XmlNode xn in xml)
            {
                sd.Add(xn.Name, xn.InnerText);
            }
            return sd;
        }




        //生成签名  
        public static string toSign(SortedDictionary<string, object> sd)
        {
            //排序生成签名返回新string
            string buff = "";
            foreach (KeyValuePair<string, object> pair in sd)
            {
                if (pair.Value == null)
                {
                    ApplicationLog.Write("参数内部含有值为null的字段!：" + pair.Key);
                    //throw new WxPayException("统一下单xml内部含有值为null的字段!");
                }

                if (pair.Key != "sign" && pair.Value.ToString() != "")
                {
		    buff += pair.Key + "=" + pair.Value + "&";
                }
            }
            buff = buff.Trim('&');

            //在string后加入API KEY
            try
            {
                buff += "&key=" + Config.getPayKey();//ConfigurationSettings.AppSettings["key"].ToString();
            }
#pragma warning disable CS0168 // 声明了变量“ex”，但从未使用过
            catch (Exception ex)
#pragma warning restore CS0168 // 声明了变量“ex”，但从未使用过
            {

            }

            //MD5加密
            var md5 = MD5.Create();
            var bs = md5.ComputeHash(Encoding.UTF8.GetBytes(buff));
            var sb = new StringBuilder();
            foreach (byte b in bs)
            {
                sb.Append(b.ToString("x2"));
            }
            //所有字符转为大写
            return sb.ToString().ToUpper();
        }

        /**
        * 生成时间戳，标准北京时间，时区为东八区，自1970年1月1日 0点0分0秒以来的秒数
         * @return 时间戳
        */
        public static string GenerateTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }

        /**
        * 生成随机串，随机串包含字母或数字
        * @return 随机串
        */
        public static string GenerateNonceStr()
        {
            return Guid.NewGuid().ToString().Replace("-", "");
        }
    }
}

